﻿using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Ufangx.Xss;
using YFurion.Controllers.Extensions;

namespace YFurion.Security.XSS.Filters
{
    public class XSSFilter : IAsyncActionFilter, IOrderedFilter
    {
        /// <summary>
        /// 过滤器排序
        /// </summary>
        public const int FilterOrder = 10000;

        /// <summary>
        /// 排序属性
        /// </summary>
        public int Order => FilterOrder;

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            // 获取动作方法描述器
            ControllerActionDescriptor controllerActionDescriptor = context.ActionDescriptor.AsControllerActionDescriptor();
            // 判断是否贴有XSS过滤特性
            if (controllerActionDescriptor.MethodInfo.IsDefined(typeof(XSSFilterAttribute)) ||
                controllerActionDescriptor.MethodInfo.DeclaringType.IsDefined(typeof(XSSFilterAttribute))
                )
            {
                //获取Action参数集合
                IList<ParameterDescriptor> ps = context.ActionDescriptor.Parameters;
                //遍历参数集合
                foreach (ParameterDescriptor p in ps)
                {
                    object value = context.ActionArguments[p.Name];
                    if (value != null)
                    {
                        //当参数等于字符串
                        if (p.ParameterType.Equals(typeof(string)))
                        {
                            RichText richText = value.ToString();
                            context.ActionArguments[p.Name] = richText.ToString();
                        }
                        else if (p.ParameterType.IsClass)//当参数等于类
                        {
                            ModelFieldFilter(p.Name, p.ParameterType, value);
                        }
                    }
                }
            }
            await next();
        }

        /// <summary>
        /// 遍历修改类的字符串属性
        /// </summary>
        /// <param name="key">类名</param>
        /// <param name="t">数据类型</param>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        private object ModelFieldFilter(string key, Type t, object obj)
        {
            if (obj != null)
            {
                //获取类的属性集合
                PropertyInfo[] pps = t.GetProperties();

                foreach (PropertyInfo pp in pps)
                {
                    object value = pp.GetValue(obj);
                    if (value != null)
                    {
                        //当属性等于字符串
                        if (pp.PropertyType.Equals(typeof(string)))
                        {
                            RichText richText = value.ToString();
                            pp.SetValue(obj, richText.ToString());
                        }
                        else if (pp.PropertyType.IsClass)//当属性等于类进行递归
                        {
                            pp.SetValue(obj, ModelFieldFilter(pp.Name, pp.PropertyType, value));
                        }
                    }
                }
            }

            return obj;
        }
    }
}
